﻿ namespace VehicleRental.API.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http;
    using VehicleRental.API.Models;
    using VehicleRental.Data;
    using VehicleRental.Models;

    public class PlacesController : BaseApiController
    {

        [HttpGet, ActionName("closest")]
        public HttpResponseMessage GetClosest([FromBody]CoordinateModel coordinates)
        {
            return this.ExecuteOperationAndHandleExceptions(() =>
            {
                var filteredPlaces = this.GetAll().Where(p => Math.Abs(p.Latitude - coordinates.Latitude) <= 1 && 
                                        Math.Abs(p.Longitude - coordinates.Longitude) <= 1);
            
                var response = this.Request.CreateResponse(HttpStatusCode.OK, filteredPlaces);

                return response;
            });
        }

        [HttpGet, ActionName("by-type")]
        public HttpResponseMessage GetClosest([FromBody]ICollection<VehicleType> vehicleTypes)
        {
            return this.ExecuteOperationAndHandleExceptions(() =>
            {
                var filteredPlaces = this.GetAll().Where(p => vehicleTypes.All(type => p.SupportedVehicleTypes.Contains(type)));

                var response = this.Request.CreateResponse(HttpStatusCode.OK, filteredPlaces);

                return response;
            });
        }

        [HttpGet, ActionName("by-id")]
        public HttpResponseMessage CreatePlace([FromUri]int placeId)
        {
            return this.ExecuteOperationAndHandleExceptions(() =>
            {
                VehicleRentalContext context = new VehicleRentalContext();

                Place currentPlace = context.Places.FirstOrDefault(p => p.Id == placeId);

                if (currentPlace == null)
                {
                    throw new ArgumentException(string.Format("Place with ID:{0}, doesn't exist", placeId));
                }

                var response = this.Request.CreateResponse(HttpStatusCode.Created, PlaceCreatedModel.Parse(currentPlace));

                return response;
            });
        }

        [HttpPost, ActionName("create")]
        public HttpResponseMessage CreatePlace([FromBody]PlaceCreateModel inputPlace)
        {
            return this.ExecuteOperationAndHandleExceptions(() =>
            {
                VehicleRentalContext context = new VehicleRentalContext();

                Place currentPlace = context.Places.FirstOrDefault(p => p.Title == inputPlace.Title &&
                            p.Latitude == inputPlace.Latitude &&
                            p.Longitude == inputPlace.Longitude);

                if (currentPlace != null)
                {
                    throw new ArgumentException(string.Format("There is already place with name {0} at [{1}:{2}]",
                                                        inputPlace.Title, inputPlace.Longitude, inputPlace.Latitude));
                }

                currentPlace = new Place()
                {
                    Address = inputPlace.Address,
                    Description = inputPlace.Description,
                    ImageSource = inputPlace.ImageSource,
                    Latitude = inputPlace.Latitude,
                    Longitude = inputPlace.Longitude,
                    SupportedVehicleTypes = inputPlace.SupportedVehicleTypes,
                    Title = inputPlace.Title
                };

                context.Places.Add(currentPlace);
                context.SaveChanges();

                foreach (VehicleModel currentVehicleModel in inputPlace.Vehicles)
                {
                    Vehicle currentVehicle = VehicleModel.Parse(currentVehicleModel);
                    currentPlace.Vehicles.Add(currentVehicle);
                    currentVehicle.Place = currentPlace;
                    context.SaveChanges();
                }

                var response = this.Request.CreateResponse(HttpStatusCode.Created, PlaceCreatedModel.Parse(currentPlace));

                return response;
            });
        }


        [HttpGet, ActionName("all")]
        public IQueryable<PlaceModel> GetAll()
        {
            VehicleRentalContext context = new VehicleRentalContext();

            var allPlacesEntities = context.Places.Include("Vehicles");

            var allPlaces =
                from placeEntity in allPlacesEntities
                select new PlaceModel()
                {
                    Id = placeEntity.Id,
                    Address = placeEntity.Address,
                    Description = placeEntity.Description,
                    ImageSource = placeEntity.ImageSource,
                    Latitude = placeEntity.Latitude,
                    Longitude = placeEntity.Longitude,
                    Title = placeEntity.Title,
                    Vehicles =
                        from vehicleEntity in placeEntity.Vehicles
                        select new VehicleModel()
                        {
                            Id = vehicleEntity.Id,
                            IsRented = vehicleEntity.IsRented,
                            Manufacturer = vehicleEntity.Manufacturer,
                            Model = vehicleEntity.Model,
                            PricePerHour = vehicleEntity.PricePerHour,
                            RentedDate = vehicleEntity.RentedDate,
                            RentedPeriod = vehicleEntity.RentedPeriod,
                            Type = vehicleEntity.Type,
                            VehicleFee = vehicleEntity.Fee,
                            Year = vehicleEntity.Year,
                            ImageSource = vehicleEntity.ImageSource,
                            PlaceId = vehicleEntity.Place.Id
                        }
                };

            return allPlaces;
        }
    }
}
